package com.cnswhy.cloud.server.comsumer.consumer.split;

import com.cnswhy.cloud.common.core.entity.constant.CnswhyConstant;
import com.cnswhy.cloud.common.core.exception.BizException;
import com.cnswhy.cloud.common.core.mybatis.conditions.Wraps;
import com.cnswhy.cloud.common.logging.uitls.MDCUtil;
import com.cnswhy.cloud.common.rabbitmq.service.MessageService;
import com.cnswhy.cloud.common.redis.service.IdGeneratorService;
import com.cnswhy.cloud.common.redis.service.RedisService;
import com.cnswhy.cloud.server.common.entity.constant.AmqpExchange;
import com.cnswhy.cloud.server.common.entity.enumeration.AccountFlag;
import com.cnswhy.cloud.server.common.entity.enumeration.BusType;
import com.cnswhy.cloud.server.common.entity.mq.CpsOrderQueryMQ;
import com.cnswhy.cloud.server.common.entity.mq.SplitAccountMQ;
import com.cnswhy.cloud.server.comsumer.event.CpsOrderSplitEvent;
import com.cnswhy.cloud.server.core.base.BankService;
import com.cnswhy.cloud.server.core.channel.hcpay.service.HcpayService;
import com.cnswhy.cloud.server.core.entity.*;
import com.cnswhy.cloud.server.core.oem.SystemService;
import com.cnswhy.cloud.server.core.service.*;
import com.cnswhy.cloud.server.core.service.cps.CpsChannelInfoService;
import com.cnswhy.cloud.server.core.service.customer.CustomerBankService;
import com.cnswhy.cloud.server.core.service.customer.CustomerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Stack;

/**
 * 无卡分账
 */
@Component
@Slf4j
public class CpsOrderSplitConsumer implements CpsOrderSplitEvent {
    @Autowired
    RedisService redisService;
    @Autowired
    IdGeneratorService idGeneratorService;
    @Autowired
    CustomerBankService customerBankService;
    @Autowired
    SystemService systemService;
    @Autowired
    CpsChannelInfoService cpsChannelInfoService;
    @Autowired
    CpsBankRateService cpsBankRateService;
    @Autowired
    CpsTransOrderService cpsTransOrderService;
    @Autowired
    HcpayService hcpayService;
    @Autowired
    MessageService messageService;
    @Autowired
    CustomerService customerService;
    @Autowired
    SplitConfigService splitConfigService;
    @Autowired
    SplitTransRecordService splitTransRecordService;
    @Autowired
    CpsBankRateSplitService cpsBankRateSplitService;
    @Autowired
    BankService bankService;
    @Autowired
    CustomerSplitService customerSplitService;
    @Override
    public void split(CpsOrderQueryMQ cpsOrderQueryMQ) throws BizException {
        log.info("分账订单：{}",cpsOrderQueryMQ.getCpsId());
        CpsTransOrder cpsTransOrder = cpsTransOrderService.getById(cpsOrderQueryMQ.getCpsId());
        if(cpsTransOrder == null) {
            log.error("分账订单-无效CPS_TRANS_ORDER_ID:{}", cpsOrderQueryMQ.getCpsId());
            return ;
        }
        Customer customer = customerService.getById(cpsTransOrder.getCustomerId());
        String bankAbbr = cpsTransOrder.getBankAbbr();
        CpsBankRateSplit cpsBankRateSplit = null;
        if(StringUtils.isBlank(cpsTransOrder.getBankAbbr())){
            BaseBankBin baseBankBin = bankService.getBankBinByCardId(cpsTransOrder.getCardId());
             cpsBankRateSplit = cpsBankRateSplitService.getOne(Wraps.<CpsBankRateSplit>lbQ().eq(CpsBankRateSplit::getBankAbbr,baseBankBin.getBankAbbr()).eq(CpsBankRateSplit::getChannelType,cpsTransOrder.getChannelType()));
            if(cpsBankRateSplit == null){
                cpsBankRateSplit = cpsBankRateSplitService.getOne(Wraps.<CpsBankRateSplit>lbQ().eq(CpsBankRateSplit::getBankAbbr,"OTHER").eq(CpsBankRateSplit::getChannelType,cpsTransOrder.getChannelType()));
            }
        }else{
            cpsBankRateSplit = cpsBankRateSplitService.getOne(Wraps.<CpsBankRateSplit>lbQ().eq(CpsBankRateSplit::getBankAbbr,bankAbbr).eq(CpsBankRateSplit::getChannelType,cpsTransOrder.getChannelType()));
        }
        Long feeRate = cpsTransOrder.getFeeRate() - cpsBankRateSplit.getFeeRate();
        Long externFee = cpsTransOrder.getExternFee() - cpsBankRateSplit.getExternFee();
        BigDecimal feeAmt = BigDecimal.valueOf(cpsTransOrder.getTransAmt() * feeRate).divide(BigDecimal.valueOf(CnswhyConstant.rateMode)).setScale(0, BigDecimal.ROUND_HALF_UP);
        //附加手续费进入奖金池 externFee
        Long totalSplit = externFee + Long.valueOf(feeAmt.longValue());
        Stack<CustomerSplit> customerSplitStack = new Stack<>();
        while (true){
            CustomerSplit customerSplit;
            if(customer.getPromoterId() == null ){
                customerSplit = customerSplitService.getOne(Wraps.<CustomerSplit>lbQ().eq(CustomerSplit::getCustomerId,0L).eq(CustomerSplit::getDownCustomerId,customer.getId()));
            }else{
                customerSplit = customerSplitService.getOne(Wraps.<CustomerSplit>lbQ().eq(CustomerSplit::getCustomerId,customer.getPromoterId()).eq(CustomerSplit::getDownCustomerId,customer.getId()));
            }
            customerSplitStack.push(customerSplit);
            if(customer.getPromoterId() == null){
                break;
            }
            customer = customerService.getById(customer.getPromoterId());
            if(customer == null){
                break;
            }
        }
        BigDecimal total = BigDecimal.ONE;
        int level = 0;
        while(!customerSplitStack.isEmpty()){
            CustomerSplit customerSplit1 = customerSplitStack.pop();
            log.info(customerSplit1.toString());
            BigDecimal curr = total.multiply(BigDecimal.ONE.subtract(BigDecimal.valueOf(customerSplit1.getSplitRate().doubleValue() / 100)));
            total = total.subtract(curr);
            if(customerSplit1.getCustomerId().equals(Long.valueOf(0))){
                continue;
            }
            SplitTransRecord splitTransRecord = addSPlitTransRecord(cpsTransOrder,customerSplit1.getCustomerId(),feeAmt.longValue(),curr, ++ level);
            if(splitTransRecord != null){
                SplitAccountMQ splitAccountMQ = SplitAccountMQ.builder().splitTransRecordId(splitTransRecord.getId()).build();
                splitAccountMQ.setTraceId(MDCUtil.getTraceId());
                messageService.sendQueueByObject(AmqpExchange.SPLIT_ACCOUNT_MESSAGE, splitAccountMQ);
            }
        }
        SplitTransRecord splitTransRecord = addSPlitTransRecord(cpsTransOrder,cpsTransOrder.getCustomerId(),feeAmt.longValue(),total, ++ level);
        if(splitTransRecord != null){
            SplitAccountMQ splitAccountMQ = SplitAccountMQ.builder().splitTransRecordId(splitTransRecord.getId()).build();
            splitAccountMQ.setTraceId(MDCUtil.getTraceId());
            messageService.sendQueueByObject(AmqpExchange.SPLIT_ACCOUNT_MESSAGE, splitAccountMQ);
        }
    }

    public SplitTransRecord addSPlitTransRecord( CpsTransOrder cpsTransOrder,Long promoterId,Long totalSplit,BigDecimal rate,int level){
        Customer customer = customerService.getById(promoterId);

        BigDecimal feeAmt = BigDecimal.valueOf(totalSplit).multiply(rate).setScale(0, BigDecimal.ROUND_HALF_UP);
        Long splitAmt = feeAmt.longValue();
        if(splitAmt.compareTo(0L) <= 0){
            return null;
        }
        SplitTransRecord splitTransRecord1 = splitTransRecordService.getOne(
          Wraps.<SplitTransRecord>lbQ().eq(SplitTransRecord::getOrderId, cpsTransOrder.getOrderId())
          .eq(SplitTransRecord::getSplitCustomerId, promoterId)
        );
        if(splitTransRecord1 != null){
            log.error("分账记录已存在");
            return null;
        }
        SplitTransRecord splitTransRecord = SplitTransRecord.builder()
                .busType(BusType.CPS_NO_CARD)
                .customerId(cpsTransOrder.getCustomerId())
                .orderId(cpsTransOrder.getOrderId())
                .externFee(cpsTransOrder.getExternFee())
                .feeRate(cpsTransOrder.getFeeRate())
                .transAmt(cpsTransOrder.getTransAmt())
                .splitLevel(level)
                .transExternFee(cpsTransOrder.getExternFee())
                .transFeeRate(cpsTransOrder.getFeeRate())
                .mobile(cpsTransOrder.getMobile())
                .settDate(cpsTransOrder.getSettDate())
                .promoterMobile(customer.getLoginName())
                .splitFee(splitAmt)
                .splitExternFee(0L)
                .splitAmt(splitAmt)
                .splitCustomerId(promoterId)
                .promoterName(customer.getVerifyName())
                .custName(cpsTransOrder.getCustName())
                .accountFlag(AccountFlag.NONE.getVal()).build();
        splitTransRecordService.save(splitTransRecord);
        return splitTransRecord;
    }
}
